package midas

import (
	"net/http"
	"time"
	"github.com/astaxie/beego/logs"
	"encoding/json"
	"strings"
	"io/ioutil"
	"fmt"
	"gitee.com/siruihuyu/appapi/module/idgenerate"
	"strconv"
)

type WxConf struct {
	AppId    string 	`json:"appid"`
	Secret   string 	`json:"secret"`
	OfferId  string 	`json:"offer_id"`
	MidasKey string 	`json:"midas_key"`
	PF       string 	`json:"pf"`
}

type Midas struct {
	config WxConf
	client http.Client
}

// NewMidas returns a *Midas ready to use.
func NewMidas (cfg WxConf) (*Midas) {
	client := http.Client{}
	midas := &Midas{
		config: cfg,
		client: client,
	}
	return midas
}

//米大师sig签名URI
func (m *Midas) SigURI(path, midasKey string) string {
	return "&org_loc=" + path + "&method=POST&secret=" + midasKey
}

//米大师map_sig签名URI
func (m *Midas) MapSigURI(path, sessionKey string) string {
	return "&org_loc=" + path + "&method=POST&session_key=" + sessionKey
}


//米大师获取余额
func (m *Midas) GetBalance(openId, sessionKey, accessToken, zoneId string) (*GetBalanceRes,error) {

	req := &GetBalanceReq{}
	req.OpenId = openId
	req.AppId = m.config.AppId
	req.OfferId = m.config.OfferId
	req.TS = time.Now().Unix()
	req.ZoneId = zoneId
	req.PF = m.config.PF
	//req.AccessToken = accessToken

	//sig签名请求参数
	params := map[string]interface{}{
		"openid": req.OpenId,
		"appid": req.AppId,
		"offer_id":req.OfferId,
		"ts":req.TS,
		"zone_id":req.ZoneId,
		"pf": req.PF,
	}

	sigHMacSha256 := signature(params, m.SigURI(req.Path(),m.config.MidasKey), m.config.MidasKey)
	logs.Info("MidasGetBalance sigHMacSha256 [%s]", sigHMacSha256)
	req.Sig = sigHMacSha256

	//msp_sig签名参数
	params["sig"] = req.Sig
	params["access_token"] = accessToken

	mpSigHMacSha256 := signature(params, m.MapSigURI(req.Path(), sessionKey), sessionKey)
	logs.Info("MidasGetBalance mpSigHMacSha256 [%s]", mpSigHMacSha256)
	req.MpSig = mpSigHMacSha256

	//获取请求url和请求体
	url := req.URI(accessToken)
	sendBody, err := json.Marshal(req)
	if err != nil {
		return nil, err
	}

	logs.Info("MidasGetBalance sendBody %s", string(sendBody))
	logs.Info("MidasGetBalance url %s", url)

	//创建请求
	postReq, err := m.client.Post(url, "application/json; encoding=utf-8", strings.NewReader(string(sendBody)))
	if err != nil {
		return nil, err
	}

	body, _ := ioutil.ReadAll(postReq.Body)
	logs.Info("MidasGetBalance postReq [%s]", string(body))

	balanceRes := GetBalanceRes{}
	err = json.Unmarshal(body, &balanceRes)
	if err != nil {
		return nil, err
	}

	if balanceRes.Errcode != 0 {
		return nil, fmt.Errorf("errcode %d errmsg %s", balanceRes.Errcode, balanceRes.Errmsg)
	}
	return &balanceRes, nil
}


//米大师支付
func (m *Midas) Pay(openid, sessionKey, accessToken, zoneId string, buyItem BuyItem) (*MidasPayRes, error) {
	if buyItem.Amt <= 0 {
		return nil, fmt.Errorf("Amt is error : %d", buyItem.Amt)
	}

	pay := MidasPayReq{}
	pay.AppId = m.config.AppId
	pay.OfferId = m.config.OfferId
	pay.PF = m.config.PF
	pay.OpenId = openid
	pay.TS = time.Now().Unix()
	pay.ZoneId = zoneId
	//pay.AccessToken = accessToken
	bill, err := idgenerate.BillNoID()
	if err != nil {
		return nil, err
	}
	pay.BillNo = strconv.FormatInt(bill, 10)
	pay.Amt = buyItem.Amt
	pay.AppRemark = buyItem.AppRemark
	pay.PayItem = buyItem.PayItem

	//sig签名请求参数
	params := map[string]interface{}{
		"openid": 		pay.OpenId,
		"appid": 		pay.AppId,
		"offer_id":		pay.OfferId,
		"ts":			pay.TS,
		"zone_id":		pay.ZoneId,
		"pf":			pay.PF,
		"amt":			pay.Amt,
		"bill_no":		pay.BillNo,
		"pay_item":		pay.PayItem,
		"app_remark":	pay.AppRemark,
	}

	sigHMacSha256 := signature(params, m.SigURI(pay.Path(), m.config.MidasKey), m.config.MidasKey)
	logs.Info("MidasPay sigHMacSha256 [%s]", sigHMacSha256)
	pay.Sig = sigHMacSha256

	//msp_sig签名参数
	params["sig"] = pay.Sig
	params["access_token"] = accessToken

	mpSigHMacSha256 := signature(params, m.MapSigURI(pay.Path(), sessionKey), sessionKey)
	logs.Info("MidasPay mpSigHMacSha256 [%s]", mpSigHMacSha256)
	pay.MpSig = mpSigHMacSha256


	//获取请求url和请求体
	url := pay.URI(accessToken)
	sendBody, err := json.Marshal(pay)
	if err != nil {
		return nil, err
	}

	logs.Info("MidasPay sendBody %s", string(sendBody))
	logs.Info("MidasPay url %s", url)


	//创建请求
	postReq, err := http.Post(url, "application/json; encoding=utf-8", strings.NewReader(string(sendBody)))
	if err != nil {
		return nil, err
	}

	body, _ := ioutil.ReadAll(postReq.Body)
	logs.Info("MidasPay postReq [%s]", string(body))

	payRes := MidasPayRes{}
	err = json.Unmarshal(body, &payRes)
	if err != nil {
		return nil, err
	}

	if payRes.Errcode != 0 {
		return nil, fmt.Errorf("errcode %d errmsg %s", payRes.Errcode, payRes.Errmsg)
	}

	return &payRes,nil

}

//米大师赠送游戏币
//count 赠送游戏币数量
func (m *Midas) Present(openid, sessionKey, accessToken, zoneId string, count int64) (*MidasPresentRes, error) {
	if count <= 0 {
		return nil, fmt.Errorf("count can not <= 0")
	}

	present := MidasPresentReq{}

	present.OpenId = openid
	present.AppId = m.config.AppId
	present.OfferId = m.config.OfferId
	present.TS = time.Now().Unix()
	present.ZoneId = zoneId
	present.PF = m.config.PF
	bill, err := idgenerate.BillNoID()
	if err != nil {
		return nil, err
	}
	present.BillNo = strconv.FormatInt(bill, 10)
	present.PresentCounts = count

	//米大师sig签名
	sigMap := make(map[string]interface{})
	sigMap["openid"] = present.OpenId
	sigMap["appid"] = present.AppId
	sigMap["offer_id"] = present.OfferId
	sigMap["ts"] = strconv.FormatInt(present.TS, 10)
	sigMap["zone_id"] = present.ZoneId
	sigMap["pf"] = present.PF
	sigMap["bill_no"] = present.BillNo
	sigMap["present_counts"] = strconv.FormatInt(present.PresentCounts, 10)

	sigHMacSha256 := signature(sigMap, m.SigURI(present.Path(), m.config.MidasKey), m.config.MidasKey)
	logs.Info("MidasPresent sigHMacSha256 [%s]", sigHMacSha256)
	present.Sig = sigHMacSha256

	//msp_sig签名参数
	sigMap["sig"] = present.Sig
	sigMap["access_token"] = accessToken

	mpSigHMacSha256 := signature(sigMap, m.MapSigURI(present.Path(), sessionKey), sessionKey)
	logs.Info("MidasPresent mpSigHMacSha256 [%s]", mpSigHMacSha256)
	present.MpSig = mpSigHMacSha256

	//获取请求url和请求体
	url := present.URI(accessToken)
	sendBody, err := json.Marshal(present)
	if err != nil {
		return nil, err
	}

	logs.Info("MidasPresent sendBody %s", string(sendBody))
	logs.Info("MidasPresent url %s", url)

	//创建请求
	postReq, err := http.Post(url, "application/json; encoding=utf-8", strings.NewReader(string(sendBody)))
	if err != nil {
		return nil, err
	}

	body, _ := ioutil.ReadAll(postReq.Body)
	logs.Info("MidasPresent postReq [%s]", string(body))
	presentRes := MidasPresentRes{}
	err = json.Unmarshal(body, &presentRes)
	if err != nil {
		return nil, err
	}

	if presentRes.Errcode != 0 {
		return nil, fmt.Errorf("errcode %d errmsg %s", presentRes.Errcode, presentRes.Errmsg)
	}
	return &presentRes, nil
}
